#ifndef POSITION_H
#define POSITION_H

#include "Board.h"
#include "Piece.h"
#include "GameState.h"
#include <vector>
using std::vector;

class Position
{

public:
	Board board; // should be private

public:
	Position();
	//Position(Position & position);
	Position(string strPos);

	void SetFromFEN(string fenString);
	Color GetTurn();
	Piece GetPiece(Square square);
	char* GetSimplifiedHashCode();

	bool IsCheck();
	bool IsCheck(Color side);
	bool IsCheck(Color side, Square square);
	bool IsPieceWhite(Piece piece);
	bool IsPieceBlack(Piece piece);
	bool IsEmptyOrOpponent(Square square);
	bool IsOpponent(Square square);
	bool IsEmpty(Square square);
	bool IsEmptyOrColor(Square square, bool color);

	void Play(Move m);
	void Unplay(Move m);
	void SetPiece(Piece piece, Square square);
	void SetStartPosition();


public: 
	GameState gameState;
	string GetFEN();
	//string GetPseudoFEN();
	bool IsEqual(Position& pos);
	
	vector<GameState> gameStateStack;
	//bool IsThreeTimesRepetitionDraw();
	void DebugDisplay();

	
	//static bool IsEqual(stack<GameState> s1, stack<GameState> s2);
	int Evaluate();
	int Evaluate(Color color);
	int GetPlayedMoveNumber();
	bool IsWhiteToMove();
	bool IsBlackToMove();

public: 
	//bool WhiteCanCastleKingSide();
	//bool BlackCanCastleKingSide();
	//bool WhiteCanCastleQueenSide();
	//bool BlackCanCastleQueenSide();
	//int GetMovesWithoutCaptureOrPawnPush();
	//Square LastEnPassant();

};


//inline bool Position::WhiteCanCastleKingSide()
//{
//	return gameStateStack.back().whiteCanCastleKingSide;
//}
//
//inline bool Position::BlackCanCastleKingSide()
//{
//	return gameStateStack.back().blackCanCastleKingSide;
//}
//
//inline bool Position::WhiteCanCastleQueenSide()
//{
//	return gameStateStack.back().whiteCanCastleQueenSide;
//}
//
//inline bool Position::BlackCanCastleQueenSide()
//{
//	return gameStateStack.back().blackCanCastleQueenSide;
//}
//
//inline Square Position::LastEnPassant()
//{
//	return gameStateStack.back().lastEnPassant;
//}

inline bool Position::IsWhiteToMove()
{
	return gameState.turn == WHITE;
}

inline bool Position::IsBlackToMove()
{
	return gameState.turn == BLACK;
}

inline bool Position::IsEmpty(Square square){
	return Board_IsSquareEmpty(board, square);
}

inline Color Position::GetTurn()
{
	//return gameStateStack.back().intTurn;
	return gameState.turn;
}

// TODO: optimize this method
inline bool Position::IsPieceWhite(Piece piece)
{
	return (piece == W_PAWN || piece == W_ROOK || piece == W_KNIGHT
		|| piece == W_BISHOP || piece == W_QUEEN || piece == W_KING);
}

// TODO: optimize this method
inline bool Position::IsPieceBlack(Piece piece)
{
	return (piece == B_PAWN || piece == B_ROOK || piece == B_KNIGHT
		|| piece == B_BISHOP || piece == B_QUEEN || piece == B_KING);
}

inline bool Position::IsEmptyOrOpponent(Square square)
{
	Piece piece = Board_GetPiece(board, square);
	if (piece == NO_PIECE) return true;
	if (this->GetTurn() == WHITE) 
		return IsPieceBlack(piece);
	//if (this->IsBlackToMove()) return IsPieceWhite(piece);
	return IsPieceWhite(piece); //optim
}

inline bool Position::IsOpponent(Square square)
{
	Piece piece = Board_GetPiece(board, square);
	if (this->GetTurn() == WHITE) 
		return IsPieceBlack(piece);
	//if (this->IsBlackToMove()) return IsPieceWhite(piece);
	return IsPieceWhite(piece); //optim
}

inline bool Position::IsEmptyOrColor(Square square, bool color)
{
	Piece piece = this->GetPiece(square);
	if (piece == NO_PIECE) return true;
	if (color) return IsPieceWhite(piece);
	return IsPieceBlack(piece);
}

inline Piece Position::GetPiece(Square square)
{
	return Board_GetPiece(board, square);
}

#endif